package com.shujia

import scala.collection.mutable.ListBuffer

object Demo13List {
  def main(args: Array[String]): Unit = {
    /**
     * List列表：
     * 一般情况下List中存储的元素类型会保持一致
     * 元素可以重复
     * 有序的
     * 不可变的：一旦被创建后就不能进行修改了
     */
    // 创建List
    val list01: List[Int] = List[Int](1, 2, 2, 2, 2, 3, 4, 5, 6)
    println(list01)
    // 通过下标获取元素
    println(list01(5))
    //    list01(5) = 33

    // List常用的方法
    println(list01.head)
    println(list01.tail)
    println(list01.take(2))
    println(list01.max)
    println(list01.min)
    println(list01.sum)
    println(list01.size)
    println(list01.sum / list01.size)
    println(list01.length)
    println(list01.isEmpty)
    println(list01.distinct)
    println(list01.sorted)
    println(list01.reverse)
    println(list01.contains(4))

    // List常用的操作
    // map、flatMap、filter、groupBy、sort相关的、foreach

    /**
     * map：对List中的每一条数据进行处理，传入一条，返回一条
     * 需要接收一个函数f：Int => 自定返回类型
     */


    // 对List中每个元素做平方
    println(list01.map(i => i * i))

    /**
     * filter：进行过滤
     * 需要接收一个函数f：Int => Boolean
     * 如果函数f返回的是true则保留数据
     * 如果函数f返回的是false则过滤数据
     */
    // 将List中的奇数过滤出来
    println(list01.filter(i => i % 2 == 1))
    println(list01.filter(i => i % 2 == 0))

    /**
     * flatMap：对数据进行扁平化处理
     * 类似map，如果当map处理完之后返回的数据类型为集合类型或者是Array数组
     * 那么flatMap可以将返回的数据进行展开（扁平化处理）
     * 同SQL中的行转列非常相似
     * 传入一条数据，返回一个集合，最终将集合展开并返回多条数据
     * 接收一个函数f：返回值类型必须是集合或者是数组类型
     */

    val list02: List[String] = List("java,scala,python", "hadoop,hive,hbase", "spark,flink")
    // 将list02中的每一个元素中的每一个单词提取出来，最终以每一个单词作为一行进行返回
    println(list02.map(str => {
      str.split(",").toList
    }))

    println(list02.flatMap(str => {
      str.split(",").toList
    }))


    /**
     * groupBy：按照指定的字段（数据）进行分组
     * 分完组之后会返回Map类型（KV格式）
     * 以分组的字段作为Key
     * 属于同一分组的所有的数据会构建成List作为Value
     */
    val list03: List[List[String]] = List(
      List("01", "zs1", "20", "文科一班")
      , List("02", "zs2", "20", "文科一班")
      , List("03", "zs3", "22", "理科一班")
      , List("04", "zs4", "22", "理科一班")
    )
    // 按照班级分组
    println(list03.groupBy(stu => {
      stu(3)
    }))

    // 按照年龄分组
    println(list03.groupBy(stu => {
      stu(2)
    }))

    // 统计每个班级的平均年龄
    list03.groupBy(stu => {
      stu(3)
    }).map(kv => {
      val clazz: String = kv._1
      s"$clazz,${kv._2.map(s => s(2).toInt).sum / kv._2.size}"
    }).foreach(println)

    /**
     * foreach：类似map方法，只不过不需要有返回值
     * 一般用于对最终的结果进行打印
     */
    list03.foreach(println)
    println(list03)

    // sort相关的
    /**
     * sorted：对List中所有的元素按照从小到大的顺序进行排列
     * sortBy：按照指定的字段进行排序
     * sortWith：按照指定的规则进行排序
     *
     */
    val stuList: List[SortStu] = List[SortStu](
      SortStu("001", "zs", 20)
      , SortStu("003", "ls", 22)
      , SortStu("002", "ww", 21)
      , SortStu("004", "ww", 20)
      , SortStu("005", "ww", 20)
    )
    // 按照age进行排序
    stuList.sortBy(s => s.age).foreach(println) // 从小到大
    stuList.sortBy(s => -s.age).foreach(println) // 从大到小

    // 按照id进行排序
    stuList.sortBy(s => s.id).foreach(println) // 从小到大

    println("=" * 30)
    // 先按照age从小到大进行排序，如果age相同 再按照id从大到小进行排序
    stuList.sortWith((stu01, stu02) => {
      if (stu01.age == stu02.age) {
        stu01.id > stu02.id
      } else {
        stu01.age < stu02.age
      }
    }).foreach(println)

    // 可变List：ListBuffer
    // 支持List的所有操作，在这基础之上又增加了 增删改的 操作
    val lb01: ListBuffer[Int] = ListBuffer[Int](1, 2, 2, 5, 4, 6, 3)
    println(lb01)

    // 增加
    lb01.append(7)
    lb01.append(8)
    println(lb01)

    lb01 += 9
    println(lb01)

    lb01.insert(2, 3)
    println(lb01)

    // 删除
    lb01 -= 5
    println(lb01)
    lb01 -= 3 // 删除第一个出现的值
    println(lb01)

    lb01.remove(4)
    println(lb01)

    // 修改
    lb01(7) = 10
    println(lb01)

    lb01.update(6, 9)
    println(lb01)


  }

  case class SortStu(id: String, name: String, age: Int)

}
